using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using YJKRevitBase.WinForm;
using YJKGeometryFuncs;



namespace YJKCoordinate
{
    public class DrainMakerApplication
    {
        public static bool UseMessageTag
        {
            get
            {
                return DrainMakerApplication.m_buseMessageTag;
            }
            set
            {
                DrainMakerApplication.m_buseMessageTag = value;
            }
        }

        public bool IfManualStop
        {
            get
            {
                return this.m_bIfManualStop;
            }
            private set
            {
                this.m_bIfManualStop = value;
            }
        }

        public DrainMakerApplication(UIApplication ui_app, Document m_doc, int index)
        {
            this.m_nIndex = index;
            this.m_Uiapp = ui_app;
            this.m_doc = m_doc;
            this.m_ThisStack = new InputDataStack(m_doc);
            this.m_lstOutPutFamilyFilePath.Clear();
        }

        public void AddOnePoint(OneInputDataPacker input)
        {
            if (input != null)
            {
                this.m_ThisStack.AddOnePoint(input);
                return;
            }
            this.m_ThisStack.SetEnd(true);
        }

        public XYZ GetEndPointNow()
        {
            return this.m_ThisStack.GetEndPoint();
        }

        public void DeleteAllDetailCurves()
        {
            this.m_ThisStack.DeleteAllDetailCurves();
        }

        internal void DrawSlopeTag()
        {
            List<ThreeInputDataPacker> result = this.m_ThisStack.GetResult();
            if (result.Count == 0 && this.m_ThisStack.GetTwoInputDataPacker(0) != null)
            {
                TwoInputDataPakcer twoInputDataPacker = this.m_ThisStack.GetTwoInputDataPacker(0);
                XYZ point = twoInputDataPacker.GetPoint(0);
                XYZ point2 = twoInputDataPacker.GetPoint(1);
                SlopeTagMaker slopeTagMaker = new SlopeTagMaker(this.m_doc, twoInputDataPacker, Utiltiy.GetMidPoint(point, point2));
                slopeTagMaker.DrawTag();
                this.m_lstSlopeTagElment.AddRange(slopeTagMaker.ThislstElement);
                if (slopeTagMaker.ThisSlopData != null)
                {
                    this.m_AllSlopDataInfo.Add(slopeTagMaker.ThisSlopData);
                    return;
                }
            }
            else if (result.Count > 0)
            {
                XYZ point;
                XYZ point2;
                SlopeTagMaker slopeTagMaker;
                for (int i = 0; i < result.Count; i++)
                {
                    point = result[i].GetLstBoundryCurvePacker()[0].GetPoint(0);
                    point2 = result[i].GetLstBoundryCurvePacker()[0].GetPoint(1);
                    slopeTagMaker = new SlopeTagMaker(this.m_doc, result[i].GetTwoInputData(0), Utiltiy.GetMidPoint(point, point2));
                    this.AddSlopMakerValueToField(slopeTagMaker);
                }
                int index = result.Count - 1;
                point = result[index].GetLstBoundryCurvePacker()[result[index].GetLstBoundryCurvePacker().Count - 1].GetPoint(0);
                point2 = result[index].GetLstBoundryCurvePacker()[result[index].GetLstBoundryCurvePacker().Count - 1].GetPoint(1);
                slopeTagMaker = new SlopeTagMaker(this.m_doc, result[index].GetTwoInputData(1), Utiltiy.GetMidPoint(point, point2));
                this.AddSlopMakerValueToField(slopeTagMaker);
            }
        }

        public void SetFamilies(ref ProgressBarForm tempForm, IntPtr parentHandle)
        {
            FamilyCreater familyCreater = FamilyCreater.GetFamilyCreater();
            List<ThreeInputDataPacker> result = this.m_ThisStack.GetResult();
            new MyFamilyLoadOptions();
            ElementSet elementSet = new ElementSet();
            Group group = null;
            Transaction transaction = new Transaction(this.m_doc, "addFamily");
            if (result.Count + 1 > 1)
            {
                tempForm = new ProgressBarForm(result.Count + 1, ProgressBarStyle.Blocks, false);
                tempForm.SetNoneCancle();
                tempForm.SetMaxValue(result.Count + 1);
                tempForm.Show(new WindowHandle(parentHandle));
            }
            try
            {
                transaction.Start();
                for (int i = 0; i < result.Count; i++)
                {
                    if (tempForm != null)
                    {
                        if (tempForm.IsDisposed)
                        {
                            this.IfManualStop = true;
                            transaction.RollBack();
                            return;
                        }
                        tempForm.RefreshProgressBar();
                        if (tempForm.IsDisposed)
                        {
                            this.IfManualStop = true;
                            transaction.RollBack();
                            return;
                        }
                    }
                    foreach (BoundryCurvePakcer boundryCurvePakcer in result[i].GetLstBoundryCurvePacker())
                    {
                        if (!this.useFamily(boundryCurvePakcer, elementSet))
                        {
                            this.m_lstOutPutFamilyFilePath.Add(familyCreater.SetResultData(this.m_Uiapp, boundryCurvePakcer, boundryCurvePakcer.Deep));
                            this.m_lstRealStartPoints.Add(familyCreater.GetRealStartPoint());
                            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(this.m_lstOutPutFamilyFilePath[this.m_lstOutPutFamilyFilePath.Count - 1]);
                            FamilySymbol familySymbol = null;
                            this.m_doc.LoadFamilySymbol(this.m_lstOutPutFamilyFilePath[this.m_lstOutPutFamilyFilePath.Count - 1], fileNameWithoutExtension, out familySymbol);
                            familySymbol.Activate();
                            elementSet.Insert(this.m_doc.Create.NewFamilyInstance(this.m_lstRealStartPoints[this.m_lstRealStartPoints.Count - 1], familySymbol, (Autodesk.Revit.DB.Structure.StructuralType)3));
                            File.Delete(this.m_lstOutPutFamilyFilePath[this.m_lstOutPutFamilyFilePath.Count - 1]);
                            this.m_dDeep = boundryCurvePakcer.Deep;
                        }
                    }
                }
                BoundryCurvePakcer boundryCurvePakcer2 = null;
                if (result.Count == 0 && this.m_ThisStack.GetTwoInputDataPacker(0) != null)
                {
                    TwoInputDataPakcer twoInputDataPacker = this.m_ThisStack.GetTwoInputDataPacker(0);
                    double num = twoInputDataPacker.GetParameters(1)[UseParameterEnum.Depth];
                    double num2 = twoInputDataPacker.GetParameters(1)[UseParameterEnum.Thickness];
                    double num3 = twoInputDataPacker.GetParameters(1)[UseParameterEnum.FlateWidth];
                    twoInputDataPacker.GetFamilyFileIndex(0);
                    double[] valueParams = new double[]
					{
						twoInputDataPacker.GetParameters(1)[UseParameterEnum.Depth],
						twoInputDataPacker.GetParameters(1)[UseParameterEnum.Thickness],
						twoInputDataPacker.GetParameters(1)[UseParameterEnum.FlateWidth],
						(double)twoInputDataPacker.GetFamilyFileIndex(0)
					};
                    boundryCurvePakcer2 = new BoundryCurvePakcer(twoInputDataPacker.GetPoint(0), twoInputDataPacker.GetPoint(1), Utiltiy.GetNormalLineBoundryCurves(twoInputDataPacker.GetPoint(0), twoInputDataPacker.GetPoint(1), twoInputDataPacker.GetParameters(1)), false, valueParams);
                    this.useFamily(boundryCurvePakcer2, elementSet);
                    this.m_dDeep = boundryCurvePakcer2.Deep;
                }
                Line line = null;
                if (this.m_ThisStack.GetTwoInputDataPacker(0) != null)
                {
                    line = this.m_ThisStack.GetTwoInputDataPacker(0).StartLine;
                }
                foreach (Element element in this.m_lstSlopeTagElment)
                {
                    if (element != null)
                    {
                        elementSet.Insert(element);
                    }
                }
                if (elementSet.Size > 0)
                {
                    group = this.m_doc.CreatYJKGroup(elementSet);
                }
                transaction.Commit();
                if (group != null)
                {
                    DrainBuryData.CreatSchema(this.m_doc, "43FEE925-0EBE-45D8-BA6F-72A4411E065A", "DrainBuryData");
                    DrainBuryDataStruct drainBuryDataStruct = new DrainBuryDataStruct();
                    List<string> collection = new List<string>();
                    List<Line> list = new List<Line>();
                    foreach (ThreeInputDataPacker threeInputDataPacker in result)
                    {
                        foreach (BoundryCurvePakcer boundryCurvePakcer3 in threeInputDataPacker.GetLstBoundryCurvePacker())
                        {
                            if (!boundryCurvePakcer3.IfCorner)
                            {
                                collection = new List<string>();
                                list = new List<Line>();
                                foreach (Curve curve in boundryCurvePakcer3.LstBoundryCurves)
                                {
                                    list.Add(curve as Line);
                                }
                                if (DataSerializeDeserialize.LineToString(list, out collection))
                                {
                                    drainBuryDataStruct.m_lstLineString.AddRange(collection);
                                }
                            }
                        }
                    }
                    if (result.Count == 0 && boundryCurvePakcer2 != null)
                    {
                        collection = new List<string>();
                        list = new List<Line>();
                        foreach (Curve curve2 in boundryCurvePakcer2.LstBoundryCurves)
                        {
                            list.Add(curve2 as Line);
                        }
                        if (DataSerializeDeserialize.LineToString(list, out collection))
                        {
                            drainBuryDataStruct.m_lstLineString.AddRange(collection);
                        }
                    }
                    XYZ point = (group.Location as LocationPoint).Point;
                    DataSerializeDeserialize.PointToString(point, out drainBuryDataStruct.m_strLocationPoint);
                    drainBuryDataStruct.m_strDeep = this.m_dDeep.ToString();
                    drainBuryDataStruct.m_strGroup = this.m_nIndex.ToString();
                    DataSerializeDeserialize.PointToString(group.get_BoundingBox(null).Max, out drainBuryDataStruct.m_strMaxPoint);
                    DataSerializeDeserialize.PointToString(group.get_BoundingBox(null).Min, out drainBuryDataStruct.m_strMinPoint);
                    foreach (SlopDataInfo slopDataInfo in this.m_AllSlopDataInfo)
                    {
                        drainBuryDataStruct.m_lstSlopeString.Add(slopDataInfo.ToString());
                    }
                    if (null != line)
                    {
                        DataSerializeDeserialize.LineToString(line, out drainBuryDataStruct.m_strStartLine);
                    }
                    DrainBuryData.BuryDataToDrain("43FEE925-0EBE-45D8-BA6F-72A4411E065A", group, "DrainBuryData", drainBuryDataStruct);
                }
            }
            catch (Exception)
            {
                if (transaction.HasStarted())
                {
                    transaction.RollBack();
                }
            }
            finally
            {
                if (tempForm != null && !tempForm.IsDisposed)
                {
                    tempForm.Dispose();
                }
            }
        }

        private void AddSlopMakerValueToField(SlopeTagMaker tempSlopeMaker)
        {
            if (tempSlopeMaker != null)
            {
                tempSlopeMaker.DrawTag();
                this.m_lstSlopeTagElment.AddRange(tempSlopeMaker.ThislstElement);
                if (tempSlopeMaker.ThisSlopData != null)
                {
                    this.m_AllSlopDataInfo.Add(tempSlopeMaker.ThisSlopData);
                }
            }
        }

        private bool useFamily(BoundryCurvePakcer input, ElementSet familySet)
        {
            if (input.IfCorner)
            {
                return false;
            }
            SubTransaction subTransaction = new SubTransaction(this.m_doc);
            subTransaction.Start();
            string text = StaticRescource.StrArrayUseFamilyNames[input.FamilyFileIndex];
            FamilySymbol familySymbol = null;
            if (!this.ifHasUseFamily(text, out familySymbol))
            {
                string text2 = StaticRescource.StrUseFamilyPath + text + StaticRescource.StrRfa;
                this.m_doc.LoadFamilySymbol(text2, text, out familySymbol);
            }
            if (familySymbol != null)
            {
                familySymbol.Activate();
                FamilyInstance familyInstance = this.m_doc.Create.NewFamilyInstance(input.GetPoint(0), familySymbol, (Autodesk.Revit.DB.Structure.StructuralType)3);
                Parameter parameter = familyInstance.GetParametersByName(StaticRescource.StrLength)[0];
                double num = input.GetPoint(0).DistanceTo(input.GetPoint(1));
                parameter.Set(num);
                parameter = familyInstance.GetParametersByName(StaticRescource.StrFlateWidth)[0];
                parameter.Set(input.FlateWidth);
                parameter = familyInstance.GetParametersByName(StaticRescource.StrThickness)[0];
                parameter.Set(input.Thickness);
                parameter = familyInstance.GetParametersByName(StaticRescource.StrDepth)[0];
                double num2 = input.Deep - input.Thickness;
                parameter.Set(num2);
                Line line = Line.CreateBound(input.GetPoint(0), input.GetPoint(1));
                Line line2 = Line.CreateUnbound(input.GetPoint(0), new XYZ(1.0, 0.0, 0.0));
                double num3;
                if (input.GetPoint(1).Y > input.GetPoint(0).Y)
                {
                    num3 = line.Direction.AngleTo(line2.Direction);
                }
                else
                {
                    num3 = line.Direction.AngleTo(line2.Direction);
                    num3 = -num3;
                }
                Line line3 = Line.CreateUnbound(input.GetPoint(0), StaticRescource.GetXYPlaneNorme(0));
                ElementTransformUtils.RotateElement(this.m_doc, familyInstance.Id, line3, num3);
                familySet.Insert(familyInstance);
            }
            subTransaction.Commit();
            return true;
        }

        private bool ifHasUseFamily(string familyName, out FamilySymbol outFamilySymobl)
        {
            ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(FamilySymbol));
            FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
            foreach (Element element in filteredElementCollector.WherePasses(elementClassFilter).ToElements())
            {
                if (element.Name.Equals(familyName))
                {
                    outFamilySymobl = (element as FamilySymbol);
                    return true;
                }
            }
            outFamilySymobl = null;
            return false;
        }

        private static bool m_buseMessageTag = true;

        private Document m_doc;

        private UIApplication m_Uiapp;

        private InputDataStack m_ThisStack;

        private List<string> m_lstOutPutFamilyFilePath = new List<string>();

        private List<XYZ> m_lstRealStartPoints = new List<XYZ>();

        private bool m_bIfManualStop;

        private int m_nIndex;

        private double m_dDeep;

        private List<Element> m_lstSlopeTagElment = new List<Element>();

        private List<SlopDataInfo> m_AllSlopDataInfo = new List<SlopDataInfo>();
    }
}
